home *** CD-ROM | disk | FTP | other *** search
- #ifdef UNIX
- /*
- * Timers and process delays work differently under POSIX. The entire system
- * is driven on a single select() call, which uses the timeout to detect alarms
- * and the file descriptors to detect input. An itimer is used to allow
- * keyboard input to continue during lengthy activities --- which I tried to
- * avoid for portability reasons, but it behaves *real* ugly otherwise.
- * Especially when LakeSW.ampr.org lets 350K of SMTP mail pile up...
- */
-
- /* DO NOT allow this file to be optimized, since there is a bug in
- GCC 4.6.x that causes code in ding() to DEVOUR CPU time */
-
-
- #ifndef _lint
- #define J_FREE_HACK 1 /* this eliminates a compiler warning */
- #endif
-
- #include "global.h"
- #include "ctype.h"
- #ifdef linux
- #undef IS_LITTLE_ENDIAN /* to avoid a re-definition warning */
- #endif
- #include <sys/stat.h>
- #include <sys/wait.h>
- #include <signal.h>
- #include "hardware.h"
- #include "commands.h"
- #ifndef _SYS_TIME_H
- #include <sys/time.h>
- #endif
- #include "timer.h"
- #include "proc.h"
- #include "socket.h"
- #include "session.h"
- #ifdef ALPHATEST
- #include "main.h"
- #endif
-
- #ifdef NO_GETTOD
- #include <sys/timeb.h>
- #endif
-
- #if !defined(_lint)
- static char rcsid[] OPTIONAL = "$Id: unix.c,v 1.29 1997/09/14 14:37:46 root Exp root $";
- #endif
-
- /* and undo a collision avoidance, since we need the real one */
- #undef malloc
- #undef free
- #if 0 /* shouldn't need - should be in stdlib */
- extern void *malloc (size_t);
- extern void free (void *);
- #endif
-
- #ifdef SETPSINFO
- int tnos_putenv (const char *envstr);
- void fix_env (void);
- #endif
- static void deinit_tick(void);
-
- /* some versions of GNU libc (at least some for Linux) have a bad bug
- that once it happens, a call to __libc_free() never returns. These
- two variables (along with code in ding() and j_free()) are here to
- keep this from disabling a system indefinitely. If a call to free
- takes longer than 60 seconds to return, then TNOS is exited.
- */
-
- static int within_a_free_call = 0;
- static int time_in_a_free_call = 0;
- #define MAX_TIME_INA_FREE_CALL 60
-
-
- /* Don't use this yet... something's still calling malloc() directly */
- #undef LMCHECK /* TEST memory allocation checker */
-
- struct io
- {
- struct io *next;
- int fd;
- void *event;
- };
-
- char Hashtab[256];
- volatile int Tick;
- int Keyboard;
- volatile int32 Clock;
- extern struct timer *Timers;
-
- static int __istate = 1;
- static struct timeval Starttime;
- static struct io *Events;
- #ifdef SHELL
- static int Shell;
- #endif
-
-
- /*****************************************************************************\
- * Miscellanous functions not found in Unix *
- \*****************************************************************************/
-
-
- unsigned long
- filelength(fd)
- int fd;
- {
- static struct stat sb;
-
- if (fstat (fd, &sb) == -1)
- return 0;
- return (unsigned long) sb.st_size;
- }
-
-
- #ifdef NEED_STRCASECMP
-
- int
- strcasecmp(s1, s2)
- register char *s1, *s2;
- {
- while (*s1 && *s2 && tolower (*s1) == tolower (*s2))
- s1++, s2++;
- return (tolower (*s1) - tolower (*s2));
- }
-
- #endif
-
-
- #ifdef NEED_STRNCASECMP
-
- int
- strncasecmp(s1, s2, n)
- register char *s1, *s2;
- int n;
- {
- while (n && *s1 && *s2 && tolower (*s1) == tolower (*s2))
- s1++, s2++, n--;
- return ((n) ? (tolower (*s1) - tolower (*s2)) : 0);
- }
-
- #endif
-
-
- char *
- strupr(s)
- char *s;
- {
- register char *p = s;
-
- while (*p)
- *p = (char) toupper (*p), p++;
- return s;
- }
-
-
- char *
- strlwr(s)
- char *s;
- {
- register char *p = s;
-
- while (*p)
- *p = (char) tolower (*p), p++;
- return s;
- }
-
-
- char *
- stpcpy(d, s)
- register char *d;
- register const char *s;
- {
- while (*s)
- *d++ = *s++;
- *d = '\0';
- return d;
- }
-
-
- char *
- itoa(n, buf, base)
- int n, base;
- char *buf;
- {
- if (base != 10)
- tprintf ("WARNING: itoa() passed radix %d\n", base);
- sprintf (buf, "%d", n);
- return buf;
- }
-
-
- /* This was in assembler, I assume for speed. */
-
- int16
- hash_ip(ipaddr)
- uint32 ipaddr;
- {
- int h;
-
- h = ((ipaddr >> 16) & 0xFFFF) ^ (ipaddr & 0xFFFF);
- return (int16) (Hashtab[((h >> 8) & 0xFF) ^ (h & 0xFF)]); /*lint !e702 !e571 */
- }
-
- /*****************************************************************************\
- * Memory interface *
- \*****************************************************************************/
-
- #ifdef LMCHECK
-
- /*
- * We track memory allocation via hash buckets. This is a fixed-size hash
- * table with variable-sized buckets: we hash an address by taking some bits
- * from it, and store the result in a slot in the bucket.
- */
-
- #define NMWHASH 4096 /* number of hash buckets - s/b power of 2 */
- #define LOGNMWH 12 /* log2(NMWHASH) */
- #define NMWHSHIFT 8 /* ptr shift for hashing */
- #define NMWHSLOT 32 /* initial slots in bucket */
-
- struct hbucket
- {
- void **ptr;
- int nptr;
- };
-
- static struct hbucket MWhashtab[NMWHASH];
-
- static void
- mwhash(void *p)
- {
- register struct hbucket *h;
- int i;
-
- h = MWhashtab + (((unsigned long) p >> NMWHSHIFT) & (NMWHASH - 1));
- if (!h->nptr) {
- h->ptr = malloc (NMWHSLOT * sizeof *h->ptr);
- memset (h->ptr, 0, NMWHSLOT * sizeof *h->ptr);
- i = 0;
- } else {
- for (i = 0; i < h->nptr; i++) {
- if (!h->ptr[i])
- break;
- }
- if (i == h->nptr) {
- h->ptr = realloc (h->ptr, (h->nptr + NMWHSLOT) * sizeof *h->ptr);
- memset (h->ptr + h->nptr, 0, NMWHSLOT * sizeof *h->ptr);
- h->nptr += NMWHSLOT;
- }
- }
- h->ptr[i] = p;
- }
-
-
- static int
- mwunhash(void *p)
- {
- register struct hbucket *h;
- int i;
-
- h = MWhashtab + (((unsigned long) p >> NMWHSHIFT) & (NMWHASH - 1));
- for (i = h->nptr; i--; ) {
- if (h->ptr[i] == p)
- break;
- }
- if (i == -1)
- return 0;
- h->ptr[i] = 0;
- return 1;
- }
- #endif
-
-
- void *
- mallocw(unsigned size)
- {
- void *p;
- int waited = 0;
-
- while ((p = malloc(size)) == (void *)0) {
- kpause (1000);
- if (++waited > 150)
- where_outta_here(1, "mallocw");
- }
- #ifdef LMCHECK
- mwhash(p);
- #endif
- return p;
- }
-
-
- void *
- callocw(cnt, size)
- unsigned cnt, size;
- {
- void *p;
-
- p = mallocw (size * cnt);
- memset(p, 0, size * cnt);
- return p;
- }
-
-
-
- static jmp_buf free_trap;
-
-
- static void
- j_free_trap (int sig OPTIONAL)
- {
- ++Ksig.kfreesegvs;
- longjmp (free_trap, 1);
- }
-
-
-
- void
- j_free(IFLINT(const) void *p)
- {
- struct sigaction sa, saold;
-
- if (p) {
- #ifdef LMCHECK
- if (!mwunhash (p)) {
- printf("\r\7WARNING: free()ing unknown pointer %lx\r\n", (unsigned long) p);
- return;
- }
- #endif
- time_in_a_free_call = 0;
- within_a_free_call = 1;
-
- /* protect free() from SEGV signals */
- sa.sa_handler = j_free_trap;
- sa.sa_flags = 0;
- (void) sigaction (SIGSEGV, &sa, &saold);
-
- if (setjmp (free_trap) == 0)
- free((void *)p);
-
- /* restore previous value for SIGV signals */
- (void) sigaction (SIGSEGV, &saold, (struct sigaction *) 0);
- within_a_free_call = 0;
- }
- }
-
-
-
- /*****************************************************************************\
- * Interrupt management - null *
- \*****************************************************************************/
-
- int
- istate()
- {
- return __istate;
- }
-
-
- int
- disable ()
- {
- sigset_t s;
- int ops;
-
- if (__istate) {
- (void) sigemptyset (&s);
- (void) sigaddset (&s, SIGALRM);
- (void) sigprocmask (SIG_BLOCK, &s, (sigset_t *) 0);
- }
- ops = __istate;
- __istate = 0;
- return ops;
- }
-
- int
- enable (void)
- {
- restore (1);
- return 0;
- }
-
- void
- restore(prs)
- int prs;
- {
- sigset_t s;
-
- if (__istate != prs) {
- (void) sigemptyset (&s);
- (void) sigaddset (&s, SIGALRM);
- (void) sigprocmask ((prs? SIG_UNBLOCK: SIG_BLOCK), &s, (sigset_t *) 0);
- }
- __istate = prs;
- }
-
-
- /*****************************************************************************\
- * Date and time functions *
- \*****************************************************************************/
-
- long
- secclock()
- {
- #ifdef NO_GETTOD
- static struct timeb t;
-
- ftime (&t);
- return t.time - Starttime.tv_sec - (Starttime.tv_usec > t.millitm * 1000);
- #else
- static struct timezone tz;
- static struct timeval tv;
-
- (void) gettimeofday (&tv, &tz);
- return tv.tv_sec - Starttime.tv_sec - (Starttime.tv_usec > tv.tv_usec); /*lint !e514 */
- #endif
- }
-
-
- long
- msclock()
- {
- #ifdef NO_GETTOD
- static struct timeb t;
-
- ftime (&t);
- t.millitm *= 1000;
- if (t.millitm < Starttime.tv_usec) {
- t.millitm += 1000000;
- t.time--;
- }
- return (t.time - Starttime.tv_sec) * 1000 +
- (t.millitm - Starttime.tv_usec) / 1000;
- #else
- static struct timezone tz;
- static struct timeval tv;
-
- (void) gettimeofday (&tv, &tz);
- if (tv.tv_usec < Starttime.tv_usec) {
- tv.tv_usec += 1000000;
- tv.tv_sec--;
- }
- return (tv.tv_sec - Starttime.tv_sec) * 1000 +
- (tv.tv_usec - Starttime.tv_usec) / 1000;
- #endif
- }
-
-
- static void
- init_time(void)
- {
- #ifdef NO_GETTOD
- struct timeb t;
-
- ftime (&t);
- Starttime.tv_sec = t.time;
- Starttime.tv_usec = t.millitm * 1000;
- #else
- struct timezone tz;
-
- (void) gettimeofday (&Starttime, &tz);
- #endif
- }
-
-
- void
- gettime(tp)
- struct time *tp;
- {
- struct tm *tm;
- #ifdef NO_GETTOD
- static struct timeb tb;
-
- ftime (&tb);
- tm = localtime (&tb.time);
- tp->ti_hund = tb.millitm / 10;
- #else
- static struct timeval tv;
- static struct timezone tz;
-
- (void) gettimeofday (&tv, &tz);
- tm = localtime ((const time_t *)&tv.tv_sec);
- tp->ti_hund = tv.tv_usec / 10000;
- #endif
- tp->ti_hour = tm->tm_hour;
- tp->ti_min = tm->tm_min;
- tp->ti_sec = tm->tm_sec;
- }
-
-
- void
- tnos_getdate(dp)
- struct date *dp;
- {
- struct tm *tm;
- #ifdef NO_GETTOD
- static struct timeb tb;
-
- ftime (&tb);
- tm = localtime (&tb.time);
- #else
- static struct timeval tv;
- static struct timezone tz;
-
- (void) gettimeofday (&tv, &tz);
- tm = localtime ((const time_t *)&tv.tv_sec);
- #endif
- dp->da_year = tm->tm_year + 1900;
- if (dp->da_year < 1970)
- dp->da_year += 100;
- dp->da_mon = tm->tm_mon + 1;
- dp->da_day = tm->tm_mday;
- }
-
-
- long
- dostounix(dp, tp)
- struct date *dp;
- struct time *tp;
- {
- static struct tm tm;
- struct tm *tx;
- long now;
-
- tm.tm_year = dp->da_year - 1900;
- tm.tm_mon = dp->da_mon - 1;
- tm.tm_mday = dp->da_day;
- tm.tm_hour = tp->ti_hour;
- tm.tm_min = tp->ti_min;
- tm.tm_sec = tp->ti_sec;
- /* This desperately needs to be fixed. How? */
- (void) time (&now);
- tx = localtime (&now);
- tm.tm_isdst = tx->tm_isdst;
- return mktime (&tm);
- }
-
-
- /*****************************************************************************\
- * Timers, I/O and scheduling *
- \*****************************************************************************/
-
- void
- register_io(fd, event)
- int fd;
- void *event;
- {
- struct io *evp;
-
- if ((evp = mallocw (sizeof *evp)) == (struct io *)0) {
- tputs ("register_io: no memory for event\n");
- where_outta_here (1, "register_io");
- }
- evp->fd = fd;
- evp->event = event;
- evp->next = Events;
- Events = evp;
- }
-
-
- void
- unregister_io(fd)
- int fd;
- {
- struct io *evp, *evc;
-
- for (evp = 0, evc = Events; evc->fd != fd; evp = evc, evc = evc->next)
- ;
- if (!evc) {
- tputs ("unregister_io: unknown fd\n");
- return;
- }
- if (evp)
- evp->next = evc->next;
- else
- Events = evc->next;
- j_free (evc);
- }
-
-
- #ifndef DUMP_CORE
- #ifdef ALPHATEST
- extern void proc_launch (void);
- #endif
-
- static void
- ouch(int sig OPTIONAL)
- {
- struct sigaction sa;
-
- sa.sa_handler = SIG_DFL;
- sa.sa_flags = 0;
- (void) sigaction (SIGSEGV, &sa, (struct sigaction *) 0);
- #ifdef SIGBUS
- (void) sigaction (SIGBUS, &sa, (struct sigaction *) 0);
- #endif
-
- #if 0
- if (fork() == 0) {
- sigaction(sig, &sa, (struct sigaction *) 0);
- (void) kill(getpid(), sig);
- }
- detach_all_asy();
- #endif
-
- if (shall_we_crash())
- crash_it_already ("SIGSEGV signal");
- #ifdef ALPHATEST
- if (++Ksig.kresumes == RESTART_COUNT || Command->proc == Curproc)
- exit (1);
-
- /* Stop alarm clock in case it's running */
- stop_timer (&Curproc->alarm);
-
- /* attempt to simply kill off the process running, not TNOS */
- if (main_exit != TRUE) {
- time_t now;
-
- log (-1, "signal SIGSEGV caught - killing process '%s' and resuming",
- Curproc->name);
- now = time ((time_t *)0);
- tcmdprintf ("*** signal SIGSEGV caught at %s*** killing process '%s' and resuming\n",
- ctime (&now), Curproc->name);
- tprintf ("\n!!! System error occurred !!!\n");
- }
- /* these were done without a signal handler, to allow dying if logging fails */
-
- /* reset the handler */
- sa.sa_handler = ouch;
- sa.sa_flags = 0;
- (void) sigaction (SIGSEGV, &sa, (struct sigaction *) 0);
- #ifdef SIGBUS
- (void) sigaction (SIGBUS, &sa, (struct sigaction *) 0);
- #endif
- switch (Curproc->ptype) {
- case PTYPE_IO:
- case PTYPE_DAEMON:
- case PTYPE_SERVER: Ksig.krestarts++;
- if (main_exit == TRUE)
- killself ();
- else
- proc_launch (); /* restart the process ;-) */
- break;
- case PTYPE_NORMAL:
- default: if (main_exit != TRUE) {
- tflush ();
- kpause (3000);
- }
- killself (); /* let the errant process be the martyr */
- }
- #endif
- }
- #endif
-
-
- static void
- ding(int i)
- {
- static struct timeval tv;
- long oclock;
- struct timeval *tvp; /*lint -esym(550,tvp) */
- #ifndef _lint
- static fd_set fds;
- struct io *evp;
- #endif
-
- /* first a check for a locked up call to free() */
- if (within_a_free_call) {
- if (++time_in_a_free_call > MAX_TIME_INA_FREE_CALL) {
- within_a_free_call = 0;
- where_outta_here(3, "a libc free() lockup");
- }
- }
-
- /* do pending output */
- if (!i) {
- tflush();
- rflush();
- }
- /* collect input events to wait on */
- #ifndef _lint
- FD_ZERO(&fds);
- for (evp = Events; evp; evp = evp->next)
- FD_SET(evp->fd, &fds);
- #endif
- /* get time until next timer; if zero, fake a very large one */
- /* if we have a nonzero argument, we're a timer tick; poll, don't block */
- if (i) {
- tv.tv_sec = tv.tv_usec = 0;
- tvp = &tv;
- } else if (!Timers)
- tvp = 0;
- else {
- /* This section gets improperly optimized in GCC 4.6.x */
- tv.tv_sec = (Timers->expiration - Clock) * MSPTICK;
- if (tv.tv_sec <= 0)
- tv.tv_sec = 0;
- tv.tv_usec = (tv.tv_sec % 1000) * 1000;
- tv.tv_sec /= 1000;
- tvp = &tv;
- }
- /* check for I/O */
- #ifndef _lint
- select (FD_SETSIZE, &fds, 0, 0, tvp);
- /* signal events for pending I/O */
- for (evp = Events; evp; evp = evp->next) {
- if (FD_ISSET(evp->fd, &fds))
- ksignal (evp->event, 1);
- }
- #endif
- /* run any due timers */
- ksignal ((volatile void *) &Tick, 1);
- /* and update the system time */
- oclock = Clock;
- Clock = msclock() / MSPTICK;
- Tick = Clock - oclock;
- }
-
-
- static void
- init_tick(void)
- {
- struct sigaction sa;
- struct itimerval it;
-
- sa.sa_flags = 0;
- sa.sa_handler = ding;
- (void) sigaction (SIGALRM, &sa, (struct sigaction *) 0);
- it.it_interval.tv_sec = 0;
- it.it_interval.tv_usec = MSPTICK * 1000;
- it.it_value = it.it_interval;
- (void) setitimer (ITIMER_REAL, &it, (struct itimerval *) 0);
- }
-
-
- static void
- deinit_tick(void)
- {
- struct itimerval it;
-
- it.it_interval.tv_sec = it.it_interval.tv_usec = 0;
- it.it_value = it.it_interval;
- (void) setitimer (ITIMER_REAL, &it, (struct itimerval *) 0);
- }
-
-
- static void
- cleanup (int sig OPTIONAL)
- {
- where_outta_here (0, "cleanup");
- }
-
-
- void
- init_sys(int no_itimer)
- {
- struct sigaction sa;
-
- init_time();
- register_io (0, &Keyboard);
-
- #ifndef DUMP_CORE
- sa.sa_handler = ouch;
- sa.sa_flags = 0;
- (void) sigaction (SIGSEGV, &sa, (struct sigaction *) 0);
- #ifdef SIGBUS
- (void) sigaction (SIGBUS, &sa, (struct sigaction *) 0);
- #endif
- #endif /* DUMP_CORE */
-
- sa.sa_handler = cleanup;
- sa.sa_flags = 0;
- (void) sigaction (SIGTERM, &sa, (struct sigaction *) 0);
-
- sa.sa_handler = SIG_IGN;
- sa.sa_flags = 0;
- (void) sigaction (SIGWINCH, &sa, (struct sigaction *) 0);
- if (!no_itimer)
- init_tick();
- }
-
-
- void
- deinit_sys()
- {
- deinit_tick();
- unregister_io(0);
- }
-
-
- void
- giveup()
- {
- /* suspend heartbeat */
- deinit_tick();
- /* block for I/O */
- ding (0);
- /* and reactivate the tick */
- init_tick();
- }
-
-
-
- #ifdef SETPSINFO
-
- static char **tnos_envp = NULLCHARP;
- static int tnos_envp_size = 0;
-
- static int
- find_env (const char *lookfor)
- {
- char **env;
- unsigned int len;
- int theindex = 0;
-
- len = strlen (lookfor);
- for (env = tnos_envp; env && *env; env++, theindex++) {
- if (!strncmp (lookfor, *env, len) && (*env)[len] == '=')
- return theindex;
- }
- return -1;
- }
-
-
- static int
- _putenv (const char *envstr)
- {
- char **new_envp;
-
- new_envp = (char **) callocw ((unsigned int)(tnos_envp_size + 2), sizeof (char *));
- if (new_envp == NULLCHARP)
- return -1;
-
- memcpy (new_envp, tnos_envp, (size_t) ((unsigned int)tnos_envp_size * sizeof (char *)));
- new_envp[tnos_envp_size++] = strdup (envstr);
- free (tnos_envp);
- tnos_envp = new_envp;
- return 0;
- }
-
-
-
- int
- tnos_putenv (const char *envstr)
- {
- char *cp;
- unsigned int len;
-
- /* sanity checking */
- if (!envstr || !*envstr || (cp = strchr (envstr, '=')) == NULLCHAR)
- return -1;
-
- /* look to see if the entry already exists, if so, error */
- len = (unsigned int) (cp - envstr);
- cp = (char *) malloc (len + 1);
- if (cp == NULLCHAR)
- return -1;
- strncpy (cp, envstr, len);
- if (find_env (cp) != -1)
- return -1;
- free (cp);
-
- /* add new entry in the environment */
- return _putenv (envstr);
- }
-
-
- #if 0
-
- char *
- getenv (const char *lookfor)
- {
- char **env = tnos_envp;
- unsigned int len;
- int theindex;
-
- len = strlen (lookfor);
- theindex = find_env (lookfor);
-
- if (theindex != -1)
- return (env[theindex] + (len + 1));
- #if 0
- return (*env + (len + 1));
- #endif
- return NULLCHAR;
- }
-
-
-
- int
- setenv (const char *name, const char *value, int overwrite)
- {
- int theindex;
- char *buf;
- int retval = 0;
-
- /* create the new entry */
- buf = (char *) callocw (1, strlen(name) + strlen(value) + 2);
- if (buf == NULLCHAR)
- return -1;
- sprintf (buf, "%s=%s", name, value);
-
- /* see if thie entry already exists */
- theindex = find_env (name);
- if (theindex == -1) { /* new entry */
- retval = _putenv (buf);
- free (buf);
- } else { /* entry exists */
- if (overwrite) {
- free (tnos_envp[theindex]);
- tnos_envp[theindex] = buf;
- } else
- free (buf);
- }
- return retval;
- }
-
-
- void
- unsetenv (const char *name)
- {
- int theindex;
-
- while ((theindex = find_env (name)) != -1) {
- free (tnos_envp[theindex]);
-
- do {
- tnos_envp[theindex] = tnos_envp[theindex + 1];
- } while (tnos_envp[++theindex]);
- tnos_envp_size--;
- }
- }
- #else
- #if !defined (__ELF__)
- #undef __environ
- #ifndef _lint
- #define __environ environ
- #endif
- #endif
-
- #ifndef _lint
- extern char **__environ;
- #endif
-
-
- void
- fix_env (void)
- {
-
- __environ = tnos_envp;
- }
- #endif
- #endif
-
- #ifdef SHELL
-
- int
- doshell(int argc, char **argv, void *p OPTIONAL)
- {
- struct sigaction sa, old_int, old_quit;
- int ac, pid;
- int pi[2];
- char const *av[4];
-
- /*
- * Under *ix, one would expect ! or shell to work like in other *ix
- * programs. Since we don't really want to emulate DOS doshell()'s
- * special handling for argv[1] == "/c" anyway :-) we will handle
- * this properly.
- *
- * argc < 2: ${SHELL:-/bin/sh}
- * >= 2: concatenate and /bin/sh -c it (NOT $SHELL)!
- */
- if (!sm_usestdio() || (Curproc->input != Command->input)) {
- tputs ("Not running on TNOS console\n");
- return 1;
- }
- if (pipe(pi) == -1) {
- tputs ("Can't create pipe for subprocess\n");
- return 1;
- }
- switch (pid = fork()) {
- case -1:
- tputs ("Fork failed\n");
- return 1;
- case 0:
- close (pi[0]);
- ac = 1;
- if (argc > 1 || (av[0] = getenv ("SHELL")) == NULLCHAR)
- av[0] = "/bin/sh";
- if (argc > 1) {
- av[ac++] = "-c";
- av[ac++] = argv[1];
- }
- av[ac] = 0;
- (void) execve (av[0], (char * const *)av, (char * const *)tnos_envp); /*lint !e605 */
- _exit(1);
- default:
- close (pi[1]);
- iosuspend();
- unregister_io (0);
- register_io (pi[0], &Shell);
- /* signal handling... */
- (void) sigemptyset (&sa.sa_mask);
- sa.sa_flags = 0;
- sa.sa_handler = SIG_IGN;
- (void) sigaction (SIGINT, &sa, &old_int);
- (void) sigaction (SIGQUIT, &sa, &old_quit);
- kwait (&Shell);
- (void) sigaction (SIGQUIT, &old_quit, 0);
- (void) sigaction (SIGINT, &old_int, 0);
- unregister_io (pi[0]);
- close (pi[0]);
- register_io (0, &Keyboard);
- ioresume();
- ac = 0;
- /* this SHOULD take care of clearing vombie processes */
- (void) waitpid (pid, &ac, WNOHANG);
- swapscreen(NULLSESSION, Command);
- }
- return 0;
- }
-
- #endif /* SHELL */
-
- #endif /* UNIX */
-
-